package adt.runlikehell;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.test.suitebuilder.annotation.LargeTest;
import android.text.AlteredCharSequence;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;

public class RunLikeHellView extends SurfaceView implements SurfaceHolder.Callback  {
	
	private Bitmap fondo_inicial;
	private Bitmap fondo_inicial_lol;
	private Bitmap fondo_gameplay;
	private Bitmap fondo_gameover;
	private Bitmap tipito;
	private Bitmap tipito2;
	private Bitmap tipito3;
	private float razon_fondo_canvas_x;
	private float razon_fondo_canvas_y;
	private int ancho, alto;
	
	private int RES_X = 800;
	private int RES_Y = 480;
	
	private int RES_TIPITO_X = 50;
	private int RES_TIPITO_Y = 70;
	

	public RunLikeHellView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		
		// register our interest in hearing about changes to our surface
        SurfaceHolder holder = getHolder();
        holder.addCallback(this);
                
        // create thread only; it's started in surfaceCreated()
        // except if used in the layout editor.
        if (isInEditMode() == false) {
            thread = new RLHThread(holder, context, new Handler(){});
        }
        
        setFocusable(true); // make sure we get key events
	}
		
	public class RLHThread extends Thread {
		
		Resources res;
		
		// *********************************************************************
		// ***************************  PUBLICOS *******************************
		// *********************************************************************
		public final int ESTADO_INICIO = 0;
		public final int ESTADO_RUNNING = 1;
		public final int ESTADO_GAMEOVER = 2;		
		public int game_state;
		
		// *********************************************************************
		// ***************************  PRIVADOS *******************************
		// *********************************************************************
		private int ancho_canvas;
		private int alto_canvas;
		private int ancho_fondo;
		private int alto_fondo;
		private int ancho_tipito;
		private int alto_tipito;
		private int ani_tipito;
		
		private SurfaceHolder surface_holder;		
		private Handler handler;		
		private Context context;
		
		// ******************************* del thread
		private boolean vive;
		
		// ******************************* del gameplay
		// la velocidad del tipito
		private float speed;
		
		// distacia recorrida
		private float distancia_recorrida;
		
		// el tipito va en el aire
		private boolean en_aire;
		
		// posicion en el eje y
		private float posicion_y;
		private float posicion_y_incial;
		
		// velocidad en el eje y
		private float velocidad_y;
		
		// aceleracion en el eje y
		private float aceleracion_y;
		
		public RLHThread(SurfaceHolder sh, Context c, Handler h){
			
			surface_holder = sh;
			handler = h;
			context = c;
			res = c.getResources();
			
			// empezando!!!!
			game_state = ESTADO_INICIO;
			
			fondo_inicial 		= BitmapFactory.decodeResource(res, R.raw.fondo1);
			fondo_inicial_lol 	= BitmapFactory.decodeResource(res, R.raw.fondo1_1);
			fondo_gameplay 		= BitmapFactory.decodeResource(res, R.raw.fondo2);
			fondo_gameover 		= BitmapFactory.decodeResource(res, R.raw.fondo3);
			tipito 				= BitmapFactory.decodeResource(res, R.raw.tipito);
			tipito2 			= BitmapFactory.decodeResource(res, R.raw.tipito2);
			tipito3 			= BitmapFactory.decodeResource(res, R.raw.tipito3);
			
			/* Estas medidas dependen de la resolucion y dpi del celular */
			ancho_fondo = fondo_inicial.getWidth();
			alto_fondo = fondo_inicial.getHeight();
			ancho_tipito = tipito.getWidth();
			alto_tipito = tipito.getHeight();
			
			/* inicializo variables del gameplay
			 * Varibales tomadas para una resolucion de 800x480
			 * ES IMPORTANTE QUE TODAS LAS VARIABLES SE TRANSFORMEN ANTES DE 
			 * SER USADAS */
			speed = 0.0f;
			distancia_recorrida = 0.0f;
			en_aire = false;
			aceleracion_y = 0.0f;
			ani_tipito = 0;
			/* Regla de 3 like a BOSS
			 * En una pantalla de 480 el tipito va en 440.0f;
			 * 480 			-> 440
			 * alto_fondo 	-> Y
			 * Y = alto_fondo * 440 / 480
			 * */
			posicion_y = 350.0f;
			posicion_y_incial = posicion_y;
			
			Log.d("", "Resoluciones: fondo: "+ancho_fondo+","+alto_fondo+"");
			Log.d("", "Resoluciones: tipito: "+ancho_tipito+","+alto_tipito+"");
			
			// le digo al hilo que ya puede arrancar
			vive = true;
		}

		// sigue siendo dentro de la clase RLHThread
		private void doDraw(Canvas canvas) {
	
			ancho_canvas = canvas.getWidth();
			alto_canvas = canvas.getHeight();			
			razon_fondo_canvas_x = (float)ancho_canvas/(float)ancho_fondo;
			razon_fondo_canvas_y = (float)alto_canvas/(float)alto_fondo;			
			
            if (game_state == ESTADO_INICIO) {
                doDrawInicio(canvas);
            } else if (game_state == ESTADO_RUNNING) {
                doDrawRunning(canvas);
            } else if (game_state == ESTADO_GAMEOVER) {
                //doDrawGameOver(canvas);
            }
        }
		
		// sigue siendo dentro de la clase RLHThread
		private void doDrawInicio(Canvas canvas) {
			canvas.drawBitmap(fondo_inicial, new Rect(0,0,ancho_fondo,alto_fondo), new Rect(0,0,ancho_canvas,alto_canvas), null);
		}
				
		private void doDrawRunning(Canvas canvas) {
			
			// posiciones ajustadas a la resolucion actual;
			int posicion_x_prima = (int)((float)(ancho_canvas*20)/(float)RES_X);
			int posicion_y_prima = (int)((float)(alto_canvas*posicion_y)/(float)RES_Y);
			
			canvas.drawBitmap(fondo_gameplay, 
					new Rect(0+(int)distancia_recorrida,0,
							ancho_fondo+(int)distancia_recorrida,alto_fondo), 
					new Rect(0,0,ancho_canvas,alto_canvas), 
					null);
			canvas.drawBitmap(fondo_gameplay, 
					new Rect(0-ancho_fondo+(int)distancia_recorrida,0,
							(int)distancia_recorrida,alto_fondo), 
					new Rect(0,0,ancho_canvas,alto_canvas), 
					null);
			if (ani_tipito%30 < 10){
				canvas.drawBitmap(tipito, 
									new Rect(0,0,ancho_tipito,alto_tipito), 
									new Rect(posicion_x_prima,(int)posicion_y_prima,
											(int)(posicion_x_prima+ancho_tipito*razon_fondo_canvas_x),
											(int)(alto_tipito*razon_fondo_canvas_y+posicion_y_prima)), 
									null);
			}
			else if (ani_tipito%30 < 20){
				canvas.drawBitmap(tipito2, 
									new Rect(0,0,ancho_tipito,alto_tipito), 
									new Rect(posicion_x_prima,(int)posicion_y_prima,
											(int)(posicion_x_prima+ancho_tipito*razon_fondo_canvas_x),
											(int)(alto_tipito*razon_fondo_canvas_y+posicion_y_prima)), 
									null);
			}
			else if (ani_tipito%30 < 30){
				canvas.drawBitmap(tipito3, 
									new Rect(0,0,ancho_tipito,alto_tipito), 
									new Rect(posicion_x_prima,(int)posicion_y_prima,
											(int)(posicion_x_prima+ancho_tipito*razon_fondo_canvas_x),
											(int)(alto_tipito*razon_fondo_canvas_y+posicion_y_prima)), 
									null);
			}
		}
		
		public void run(){
			
			long time_nuevo = System.currentTimeMillis();
			long time_viejo = 0l;
			long tiempo = 0l;
						
			while(vive){
				
				Canvas c = null;
				
				time_viejo = time_nuevo;
				time_nuevo = System.currentTimeMillis();
				
				tiempo = time_nuevo - time_viejo;
				
				if (tiempo == 0){
					tiempo = 1;
				}
				
				if (game_state == ESTADO_INICIO){
					
				}
				else if (game_state == ESTADO_RUNNING){
					
					if (en_aire){
						
						velocidad_y = velocidad_y + aceleracion_y *(float)tiempo/200.0f;					
						posicion_y = posicion_y + velocidad_y *(float)tiempo/200.0f;
						
						if (posicion_y > posicion_y_incial){
							posicion_y = posicion_y_incial;
							aceleracion_y = 0.0f;
							velocidad_y = 0.0f;
							en_aire = false;
						}
					}
					
					distancia_recorrida += 20.0f;
					if ((int)distancia_recorrida >= ancho_fondo){
						distancia_recorrida = 0.0f;
					}
					
					ani_tipito++;
					if (ani_tipito == 3000) ani_tipito =0;
				}
				
				try {
                    c = surface_holder.lockCanvas(null);
                    // synchronized (mSurfaceHolder) {
                    doDraw(c);
                    // }
                } finally {
                   
                	// do this in a finally so that if an exception is thrown
                    // during the above, we don't leave the Surface in an
                    // inconsistent state
                    if (c != null) {
                        surface_holder.unlockCanvasAndPost(c);
                    }
                }
			}
		}
		
		public void setRunning(boolean b) {
            vive = b;
        }
		
		public int getGameState() {
            synchronized (surface_holder) {
                return game_state;
            }
        }
		
		public void setGameState(int mode) {
            synchronized (surface_holder) {
                game_state = mode;
            }
        }
		
		/* Callback invoked when the surface dimensions change. */
        public void setSurfaceSize(int width, int height) {
            // synchronized to make sure these all change atomically
            synchronized (surface_holder) {
                ancho_canvas = width;
                alto_canvas = height;
            }
        }
        
	}
	
	private RLHThread thread;
	
	public RLHThread getThread() {
        return thread;
    }
	
	/* Callback invoked when the surface dimensions change. */
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        thread.setSurfaceSize(width, height);
    }
    
    public void surfaceCreated(SurfaceHolder arg0) {
        // start the thread here so that we don't busy-wait in run()
        // waiting for the surface to be created
        thread.setRunning(true);
        thread.start();
    }
    
    public void surfaceDestroyed(SurfaceHolder arg0) {
        boolean retry = true;
        thread.setRunning(false);
        while (retry) {
            try {
                thread.join();
                retry = false;

            } catch (InterruptedException e) {
            }
        }
    }

	public boolean onTouchEvent(MotionEvent event){
		
		float x = event.getX();
		float y = event.getY();
		
		if (event.getAction() == MotionEvent.ACTION_DOWN){
			
			Log.d("EVENT", "["+x+","+y+"]");			
			Float X = new Float(x/razon_fondo_canvas_x);
			Float Y = new Float(y/razon_fondo_canvas_y);
			
			if (thread.getGameState() == thread.ESTADO_INICIO){
				
				/* BOTON DE PLAY!!!! */
				// medidas tomadas a mano en la imagen 600*360
				Rect r = new Rect(398,200,398+180,200+125);
				
				if (r.contains(X.intValue(),Y.intValue())){
					Log.d("ACTION", "PLAY!!!!");
					thread.setGameState(thread.ESTADO_RUNNING);
				}
			}
			else if (thread.getGameState() == thread.ESTADO_RUNNING){
				if (!thread.en_aire){
					thread.velocidad_y = -150.0f;
					thread.aceleracion_y = 50.0f;
					thread.en_aire = true;
				}
			}
		}
		return true;
	}
}
